package com.sad.jetpack.v1.datamodel.api.extension.client.socket.ipc;

import com.sad.jetpack.v1.datamodel.api.utils.LogcatUtils;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;

public class IPCStreamUtils {

    public interface InputStreamReadingListener{

        void onLoopReading(byte[] bytes,int readIndex,int futureSize) throws Exception;

    }

    public static void handleInputStream(InputStream inputStream,int cacheSize, int futureSize,InputStreamReadingListener listener) throws Exception{
        byte[] cacheBytes=new byte[cacheSize];
        //读取进度(已读长度)
        int readIndex=0;
        // 循环读取
        while (readIndex < futureSize){
            int left_size= futureSize-readIndex;
            int readCurrCount=0;
            if (left_size<cacheSize){
                readCurrCount=inputStream.read(cacheBytes,0,left_size);
            }
            else {
                readCurrCount=inputStream.read(cacheBytes);
            }

            if (readCurrCount>0){
                byte[] c2= Arrays.copyOf(cacheBytes,readCurrCount);//将有实际内容的字节组复制出来,得到一个没有多余空位的字节组。
                if(listener!=null){
                    listener.onLoopReading(c2,readIndex,futureSize);
                }
                readIndex += readCurrCount;
            }
            else {
                throw new Exception("输入流供给侧链接关闭，无法保证已读内容的合法性!!!!");
            }
        }
    }


    public static byte[] readBytes(InputStream inputStream, int cacheSize, int futureSize) throws Exception {
        byte[] futureBytes=new byte[futureSize];
        if(futureSize<=0){
            return futureBytes;
        }
        handleInputStream(inputStream, cacheSize, futureSize, new InputStreamReadingListener() {
            @Override
            public void onLoopReading(byte[] bytes,int readIndex,int futureSize) throws Exception {
                System.arraycopy(bytes,0,futureBytes,readIndex,bytes.length);
            }
        });
        return futureBytes;
    }

    public static void writeFromInputStream(Socket targetSocket,InputStream inputStream,int cacheSize, int futureSize) throws Exception{
        handleInputStream(inputStream, cacheSize, futureSize, new InputStreamReadingListener() {
            @Override
            public void onLoopReading(byte[] bytes,int readIndex,int futureSize) throws Exception {
                boolean ws=writeBytes(targetSocket,bytes);
                if (!ws){
                    throw new Exception("socket outstream writing sth from inputstream failed !!!");
                }
            }
        });
    }

    public static void writeBytes(OutputStream outputStream,byte[] bytes) throws Exception{
        outputStream.write(bytes);
        outputStream.flush();
    }

    public static boolean writeBytes(Socket socket, byte[] bytes) throws Exception{
        if (socket==null){
            LogcatUtils.e("-------------->IO输出流:socket==null");
            return false;
        }
        if (socket.isClosed()){
            LogcatUtils.e("-------------->IO输出流:socket.isClosed");
            return false;
        }
        if (socket.isOutputShutdown()){
            LogcatUtils.e("-------------->IO输出流:socket.isOutputShutdown");
            return false;
        }
        OutputStream outputStream=socket.getOutputStream();
        writeBytes(outputStream,bytes);
        return true;
    }

}
